package com.ruoyi.qd.service.impl;

import cn.hutool.core.lang.func.LambdaUtil;
import cn.hutool.core.util.IdUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.validate.ValidatorUtil;
import com.ruoyi.qd.domain.Order;
import com.ruoyi.qd.domain.RobotQueue;
import com.ruoyi.qd.enums.OrderStatusEnum;
import com.ruoyi.qd.enums.RobotQueueStatusEnum;
import com.ruoyi.qd.enums.TradeWaterTypeEnum;
import com.ruoyi.qd.mapper.OrderMapper;
import com.ruoyi.qd.service.IOrderService;
import com.ruoyi.qd.service.ITradeWaterService;
import com.ruoyi.qd.vo.OrderAppointmentReq;
import com.ruoyi.qd.vo.OrderListByUserIdRes;
import com.ruoyi.qd.vo.OrderPageReq;
import com.ruoyi.qd.vo.OrderPageRes;
import com.ruoyi.qd.vo.TradeWaterAddReq;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import static com.ruoyi.common.core.domain.entity.table.SysUserTableDef.SYS_USER;
import static com.ruoyi.qd.domain.table.OrderTableDef.ORDER;
import static com.ruoyi.qd.domain.table.RobotTableDef.ROBOT;

/**
 * 订单Service业务层处理
 *
 * @author tushiguang
 * @date 2024-07-24
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {
    @Autowired
    private ITradeWaterService tradeWaterService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void completedOrder(Long orderId) {
        if (Objects.isNull(orderId)) {
            throw new ServiceException("订单id不能为空");
        }

        RobotQueue robotQueue = RobotQueue.create()
                .where(RobotQueue::getOrderId).eq(orderId)
                .one();
        if (Objects.isNull(robotQueue)) {
            throw new ServiceException("系统异常");
        }
        if (!Objects.equals(RobotQueueStatusEnum.PROCESS.getCode(), robotQueue.getStatus())) {
            throw new ServiceException("机器人未处理，不可完成订单！");
        }

        // 设置队列状态为完成
        RobotQueue.create()
                .setStatus(RobotQueueStatusEnum.COMPLETED.getCode())
                .where(RobotQueue::getOrderId).eq(orderId)
                .update();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void signOrder(Long orderId) {
        if (Objects.isNull(orderId)) {
            throw new ServiceException("订单id不能为空");
        }

        RobotQueue robotQueue = RobotQueue.create()
                .where(RobotQueue::getOrderId).eq(orderId)
                .one();
        if (Objects.isNull(robotQueue)) {
            throw new ServiceException("系统异常");
        }
        if (!Objects.equals(RobotQueueStatusEnum.CALL.getCode(), robotQueue.getStatus())) {
            throw new ServiceException("机器人未叫号，请耐心等待！");
        }

        // 修改订单状态为已使用
        Order.create()
                .setStatus(OrderStatusEnum.USED.getCode())
                .where(Order::getId).eq(orderId)
                .update();

        // 设置队列状态为处理中
        RobotQueue.create()
                .setStatus(RobotQueueStatusEnum.PROCESS.getCode())
                .where(RobotQueue::getOrderId).eq(orderId)
                .update();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void cancelOrder(Long orderId) {
        if (Objects.isNull(orderId)) {
            throw new ServiceException("订单id不能为空");
        }

        // 修改订单状态为用户取消
        Order.create()
                .setStatus(OrderStatusEnum.USER_CANCEL.getCode())
                .where(Order::getId).eq(orderId)
                .update();

        // 退款
        Order order = mapper.selectOneById(orderId);
        TradeWaterAddReq tradeWaterAddReq = new TradeWaterAddReq();
        tradeWaterAddReq.setAmount(order.getMoney());
        tradeWaterAddReq.setType(TradeWaterTypeEnum.PERSONAL_CANCEL_APPOINTMENT_ROBOT_REFUND.getCode());
        tradeWaterAddReq.setUserId(order.getUserId());
        tradeWaterService.add(tradeWaterAddReq);

        // 删除队列
        RobotQueue.create()
                .where(RobotQueue::getOrderId).eq(orderId)
                .remove();
    }

    @Override
    public List<OrderListByUserIdRes> listOrderByUserId(Long userId) {
        if (Objects.isNull(userId)) {
            return Collections.emptyList();
        }

        return Order.create()
                .select(ORDER.ID, ORDER.MONEY, ORDER.APPOINTMENT_TIME, ORDER.ROBOT_ID,
                        ROBOT.TITLE.as(LambdaUtil.getFieldName(OrderListByUserIdRes::getRobotTitle)),
                        ROBOT.IMAGE.as(LambdaUtil.getFieldName(OrderListByUserIdRes::getRobotImage)))
                .leftJoin(ROBOT).on(ROBOT.ID.eq(ORDER.ROBOT_ID))
                .where(Order::getUserId).eq(userId)
                .and(Order::getStatus).eq(OrderStatusEnum.PAID.getCode())
                .and(ROBOT.DEPT_ID.eq(SecurityUtils.getChooseDeptId()))
                .orderBy(Order::getAppointmentTime).asc()
                .listAs(OrderListByUserIdRes.class);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void appointment(OrderAppointmentReq orderAppointmentReq) {
        ValidatorUtil.validateEntity(orderAppointmentReq);

        BigDecimal balance = tradeWaterService.calculateBalance(orderAppointmentReq.getUserId());
        if (balance.compareTo(orderAppointmentReq.getAmount()) < 0) {
            throw new ServiceException("钱包余额不足，请充值后再预约！");
        }

        // 流水
        TradeWaterAddReq tradeWaterAddReq = new TradeWaterAddReq();
        tradeWaterAddReq.setAmount(orderAppointmentReq.getAmount());
        tradeWaterAddReq.setType(orderAppointmentReq.getType());
        tradeWaterAddReq.setUserId(orderAppointmentReq.getUserId());
        tradeWaterService.add(tradeWaterAddReq);

        // 生成订单
        Long orderId = Order.create()
                .setOrderNo(IdUtil.getSnowflake().nextIdStr())
                .setUserId(orderAppointmentReq.getUserId())
                .setRobotId(orderAppointmentReq.getRobotId())
                .setStatus(OrderStatusEnum.PAID.getCode())
                .setAppointmentTime(orderAppointmentReq.getAppointmentTime())
                .setMoney(orderAppointmentReq.getAmount())
                .saveOpt()
                .orElseThrow(() -> new ServiceException("订单保存失败")) // 保存失败抛出异常
                .getId();

        // 生成队列
        RobotQueue.create()
                .setOrderId(orderId)
                .setAppointmentTime(orderAppointmentReq.getAppointmentTime())
                .setRobotId(orderAppointmentReq.getRobotId())
                .setStatus(RobotQueueStatusEnum.LINE.getCode())
                .setUserId(orderAppointmentReq.getUserId())
                .save();
    }

    /**
     * 查询订单
     *
     * @param id 订单主键
     * @return 订单
     */
    @Override
    public Order selectOrderById(Long id) {
        return mapper.selectOneById(id);
    }

    @Override
    public Page<OrderPageRes> selectOrderPage(PageDomain pageDomain, OrderPageReq orderPageReq) {
        return Order.create()
                .select(ORDER.ALL_COLUMNS, SYS_USER.USER_NAME,
                        ROBOT.TITLE.as(LambdaUtil.getFieldName(OrderPageRes::getRobotTitle)),
                        ROBOT.SN.as(LambdaUtil.getFieldName(OrderPageRes::getRobotSn)))
                .leftJoin(SYS_USER).on(SYS_USER.USER_ID.eq(ORDER.USER_ID))
                .leftJoin(ROBOT).on(ROBOT.ID.eq(ORDER.ROBOT_ID))
                .where(SYS_USER.USER_NAME.like(orderPageReq.getUserName()))
                .and(ORDER.ORDER_NO.eq(orderPageReq.getOrderNo()))
                .and(ROBOT.TITLE.like(orderPageReq.getRobotTitle()))
                .and(ROBOT.SN.eq(orderPageReq.getRobotSn()))
                .and(ORDER.STATUS.eq(orderPageReq.getStatus()))
                .orderBy(ORDER.ID.desc())
                .pageAs(new Page<>(pageDomain.getPageNum(), pageDomain.getPageSize()), OrderPageRes.class);
    }

    /**
     * 查询订单列表
     *
     * @param order 订单
     * @return 订单
     */
    @Override
    public List<Order> selectOrderList(Order order) {
        QueryWrapper query = buildWrapper(order);
        return mapper.selectListByQuery(query);
    }

    public QueryWrapper buildWrapper(Order order) {
        return query()
                .where(ORDER.USER_ID.eq(order.getUserId()))
                .and(ORDER.ROBOT_ID.eq(order.getRobotId()))
                .and(ORDER.STATUS.eq(order.getStatus()));
    }

    /**
     * 新增订单
     *
     * @param order 订单
     * @return 结果
     */
    @Override
    public int insertOrder(Order order) {
        return mapper.insertSelective(order);
    }

    /**
     * 修改订单
     *
     * @param order 订单
     * @return 结果
     */
    @Override
    public int updateOrder(Order order) {
        return mapper.update(order);
    }

    /**
     * 批量删除订单
     *
     * @param ids 需要删除的订单主键
     * @return 结果
     */
    @Override
    public int deleteOrderByIds(Long[] ids) {
        return mapper.deleteBatchByIds(Arrays.asList(ids));
    }

    /**
     * 删除订单信息
     *
     * @param id 订单主键
     * @return 结果
     */
    @Override
    public int deleteOrderById(Long id) {
        return mapper.deleteById(id);
    }
}
